package com.heima.admin.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.heima.admin.feign.ArticleFeign;
import com.heima.admin.feign.WemediaFeign;
import com.heima.admin.mapper.AdChannelMapper;
import com.heima.admin.mapper.AdSensitiveMapper;
import com.heima.admin.service.WemediaNewsAutoScanService;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.constants.aliyun.AliyunConstants;
import com.heima.common.fastdfs.FastDFSClient;
import com.heima.model.admin.dtos.NewsAuthDto;
import com.heima.model.admin.pojos.AdChannel;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.pojos.ApArticleConfig;
import com.heima.model.article.pojos.ApArticleContent;
import com.heima.model.article.pojos.ApAuthor;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.media.dtos.WmNewsVo;
import com.heima.model.media.pojos.WmNews;
import com.heima.model.media.pojos.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import com.mongodb.bulk.IndexRequest;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.log4j.Log4j2;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;

/**
 * @作者 itcast
 * @创建日期 2020/9/27 10:51
 **/
@Service
@Slf4j
public class WemediaNewsAutoScanServiceImpl implements WemediaNewsAutoScanService {
    @Autowired
    private WemediaFeign wemediaFeign;

    @GlobalTransactional
    @Override
    public void autoScanByMediaNewsId(Integer id) {
        log.info("自动审核任务开始  ==> 待审核文章id {}",id);
        // 参数校验
        if(id == null){
            log.error("当前的审核id为空");
            return;
        }
        // 远程获取自媒体文章
        WmNews wmNews = wemediaFeign.findById(id);
        if(wmNews == null){
            log.error("审核的自媒体文章不存在,自媒体的id: {} ",id);
            return;
        }
        // 文章状态为4(人工审核通过)  直接保存数据的和创建索引
        if(wmNews.getStatus() == 4){
            // 保存数据
            log.info("该文章为人工审核通过文章，直接存储到数据库中  end..");
            saveAppArticle(wmNews);
            return;
        }
        // 文章状态为8  文章状态为8
        //发布时间>当前时间
        //直接保存数据
        if(wmNews.getStatus() == 8 && wmNews.getPublishTime().getTime()<=System.currentTimeMillis()){
            // 保存数据
            log.info("该文章为审核通过待发布文章，直接存储到数据库中  end..");
            saveAppArticle(wmNews);
            return;
        }
        // 文章状态为1，待审核
        if(wmNews.getStatus() == 1){
            // 抽取文章内容中的纯文本和图片
            Map<String, Object> contentAndImagesResult = handleTextAndImages(wmNews);
            // 文本审核
            log.info("=============阿里云 内容检测开始=============");
            boolean textScanResult = handleTextScan((String) contentAndImagesResult.get("content"), wmNews);
            if(!textScanResult) return;
            // 图片审核

            log.info("=============阿里云 图片检测开始=============");
            boolean imageScanResult = handleImageScan((List<String>) contentAndImagesResult.get("images"), wmNews);
            if(!imageScanResult) return;

            // 自管理敏感词审核
            log.info("=============自管理 敏感词检测开始=============");
            boolean sensitiveResult = handleSensitive((String) contentAndImagesResult.get("content"), wmNews);
            if(!sensitiveResult) return;


            log.info("=============文章审核完毕=============");
            // 发布时间大于当前时间 修改文章状态为8
            if(wmNews.getPublishTime().getTime() > System.currentTimeMillis()){
                updateWmNews(wmNews,(short)8,"审核通过");
                return;
            }
            // 审核通过，修改自媒体文章状态为9  保存app端相关文章信息
            saveAppArticle(wmNews);
        }
    }
    @Override
    public PageResponseResult findNews(NewsAuthDto dto) {
        // 分页查询
        PageResponseResult responseResult = wemediaFeign.findList(dto);
        responseResult.setHost(fileServerUrl);
        return responseResult;
    }
    @Override
    public ResponseResult findOne(Integer id) {
        // 参数检查
        if (id==null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        // 查询数据
        WmNewsVo wmNewsVo = wemediaFeign.findWmNewsVo(id);
        ResponseResult responseResult = ResponseResult.okResult(wmNewsVo);
        responseResult.setHost(fileServerUrl);
        return responseResult;
    }
    @Override
    public ResponseResult updateStatus(Integer type, NewsAuthDto dto) {
        // 参数检查
        if(dto ==null || dto.getId()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        // 查询文章
        WmNews wmNews = wemediaFeign.findById(dto.getId());
        if(wmNews == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        // 根据驳回和通过 分别进行不同的修改操作
        if(type == 0){
            // 审核未通过
            updateWmNews(wmNews, ((short) 2),dto.getMsg());
        }else if (type == 1){
            updateWmNews(wmNews, ((short) 4),"人工审核通过");
        }
        return ResponseResult.okResult();
    }
    @Autowired
    private AdSensitiveMapper adSensitiveMapper;
    /**
     * 敏感词信息检查
     * @param content
     * @param wmNews
     * @return
     */
    private boolean handleSensitive(String content, WmNews wmNews) {
        boolean flag = true;
        List<String> allSensitive = adSensitiveMapper.findAllSensitive();
        // 初始化敏感词map
        SensitiveWordUtil.initMap(allSensitive);
        // 文章内容自管理敏感词过滤
        Map<String, Integer> resultMap = SensitiveWordUtil.matchWords(content);
        if(resultMap.size() > 0){
            log.error("发布的文章中包含敏感词汇 : {}",resultMap);
            updateWmNews(wmNews,(short)2,"文章中包含了敏感词");
            flag = false;
        }
        return flag;
    }
    @Autowired
    FastDFSClient fastDFSClient;
    @Autowired
    GreenImageScan greenImageScan;
    @Value("${fdfs.url}")
    String fileServerUrl;

    private boolean handleImageScan(List<String> images, WmNews wmNews) {
        boolean flag = true;
        if(images == null){
            return true;
        }
        List<byte[]> imageList = new ArrayList<>();
        try {
            for (String imageUrl : images) {
                imageUrl = imageUrl.replace(fileServerUrl, "");
                int index = imageUrl.indexOf("/");
                String groupName = imageUrl.substring(0, index);
                String pathName = imageUrl.substring(index+1);
                byte[] download = fastDFSClient.download(groupName, pathName);
                imageList.add(download);
            }

            Map map = greenImageScan.imageScan(imageList);
            // 审核不通过
            String result = (String)map.get(AliyunConstants.SCAN_RESULT_SUGGESTION);
            if(!AliyunConstants.SCAN_RESULT_TYPE_PASS.equals(result)){
                if(AliyunConstants.SCAN_RESULT_TYPE_BLOCK.equals(result)){
                    // 修改自媒体文章的状态,并告知审核失败
                    updateWmNews(wmNews,(short)2,"文章中有图片违规");
                    flag = false;
                }

                if(AliyunConstants.SCAN_RESULT_TYPE_REVIEW.equals(result)){
                    updateWmNews(wmNews,(short)3,"文章中有图片需要进一步人工审核是否违规");
                    flag = false;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("图片审核 读取图片信息出现异常 : {}",e.getCause());
            flag = false;
        }
        return flag;
    }

    @Autowired
    private GreenTextScan greenTextScan;
    /**
     * 通过阿里云 处理文本扫描
     * @param content
     * @param wmNews
     * @return 检查通过 true  不通过 false
     */
    private boolean handleTextScan(String content, WmNews wmNews) {
        boolean flag = true;
        try {
            Map map = greenTextScan.greeTextScan(content);
            String result = (String) map.get(AliyunConstants.SCAN_RESULT_SUGGESTION);
            if(!AliyunConstants.SCAN_RESULT_TYPE_PASS.equals(result)){
                if(AliyunConstants.SCAN_RESULT_TYPE_BLOCK.equals(result)){
                    updateWmNews(wmNews,(short)2,"文章内容中有敏感词汇");
                    flag = false;
                }
                if(AliyunConstants.SCAN_RESULT_TYPE_REVIEW.equals(result)){
                    updateWmNews(wmNews,(short)3,"文章中有不确定词汇");
                    flag = false;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("阿里云内容审核出现异常  文章ID: {}",wmNews.getId());
            flag = false;
        }
        return flag;
    }

    /**
     * 提取文章的文本内容 及 图片列表
     * @param wmNews
     * @return key: content 文本内容  value: 文本字符串
     *         key: images 图片内容   value: 图片url列表list集合
     */
    private Map<String,Object> handleTextAndImages(WmNews wmNews){
        // 文章的内容
        String content = wmNews.getContent();
        // 用于存储纯文本内容
        StringBuilder sb = new StringBuilder();
        // 用于存储图片url
        List<String> images = new ArrayList<String>();
        List<Map> contentList = JSONArray.parseArray(content, Map.class);
        for (Map map : contentList) {
            if ("text".equals(map.get("type"))) {
                sb.append(map.get("value"));
            }
            if ("image".equals(map.get("type"))) {
                images.add((String) map.get("value"));
            }
        }
        // 处理封面图片  type=0代表无图
        if(wmNews.getImages() !=null && wmNews.getType() !=0){
            String[] split = wmNews.getImages().split(",");
            images.addAll(Arrays.asList(split));
        }
        // 封装结果并返回
        Map<String,Object> resultMap = new HashMap();
        resultMap.put("content",sb.toString());
        resultMap.put("images",images);
        return resultMap;
    }
    /**
     * 保存app 文章相关的问题
     * @param wmNews
     */
    private void saveAppArticle(WmNews wmNews){
        // 保存app文章
        ApArticle apArticle = saveArticle(wmNews);
        // 保存app文章配置
        saveArticleConfig(apArticle);
        // 保存app文章内容
        saveArticleContent(apArticle,wmNews);
        // 修改自媒体文章的状态为9
        wmNews.setArticleId(apArticle.getId());
        updateWmNews(wmNews,(short)9,"审核通过");
        // TODO 将新的文章信息添加到es索引库
    }

    // 修改自媒体文庄状态
    private void updateWmNews(WmNews wmNews, short status, String msg) {
        wmNews.setStatus(status);
        wmNews.setReason(msg);
        wemediaFeign.updateWmNews(wmNews);
    }

    private void saveArticleContent(ApArticle apArticle, WmNews wmNews) {
        ApArticleContent apArticleContent = new ApArticleContent();
        apArticleContent.setArticleId(apArticle.getId());
        apArticleContent.setContent(wmNews.getContent());
        // Feign调用文章服务  存储文章内容信息
        articleFeign.saveArticleContent(apArticleContent);
    }

    private void saveArticleConfig(ApArticle apArticle) {
        ApArticleConfig apArticleConfig = new ApArticleConfig();
        apArticleConfig.setArticleId(apArticle.getId());
        apArticleConfig.setIsForward(true); // 可否转发
        apArticleConfig.setIsDelete(false); // 删除状态
        apArticleConfig.setIsDown(true);  // false 下架  true 上架
        apArticleConfig.setIsComment(true); // 是否可评论
        articleFeign.saveArticleConfig(apArticleConfig);
    }

    @Autowired
    ArticleFeign articleFeign;

    @Autowired
    AdChannelMapper adChannelMapper;

    private ApArticle saveArticle(WmNews wmNews){
        // 文章基本信息设置
        ApArticle apArticle = new ApArticle();
        apArticle.setTitle(wmNews.getTitle());
        apArticle.setLayout(wmNews.getType());
        apArticle.setImages(wmNews.getImages());
        apArticle.setCreatedTime(new Date());
        apArticle.setPublishTime(wmNews.getPublishTime());
        // 文章作者相关信息设置
        Integer wmUserId = wmNews.getUserId();
        WmUser wmUser = wemediaFeign.findWmUserById(wmUserId);
        if(wmUser!=null){
            String wmUserName = wmUser.getName();
            ApAuthor apAuthor = articleFeign.selectAuthorByName(wmUserName);
            if(apAuthor != null){
                apArticle.setAuthorId(apAuthor.getId().longValue());
                apArticle.setAuthorName(apAuthor.getName());
            }
        }
        // 文章频道相关信息设置
        Integer channelId = wmNews.getChannelId();
        AdChannel channel = adChannelMapper.selectById(channelId);
        if(channel !=  null){
            apArticle.setChannelId(channel.getId());
            apArticle.setChannelName(channel.getName());
        }
        return articleFeign.saveArticle(apArticle);
    }
}
